home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
xlib
/
xlib06
/
xrect.asm
< prev
next >
Wrap
Assembly Source File
|
1993-09-12
|
25KB
|
685 lines
;-----------------------------------------------------------------------
; MODULE XRECT
;
; Rectangle functions all MODE X 256 Color resolutions
;
; Compile with Tasm.
; C callable.
;
;
; ****** XLIB - Mode X graphics library ****************
; ****** ****************
; ****** Written By Themie Gouthas ****************
;
; egg@dstos3.dsto.gov.au
; teg@bart.dsto.gov.au
;-----------------------------------------------------------------------
include xlib.inc
include xrect.inc
.data
; Plane masks for clipping left and right edges of rectangle.
LeftClipPlaneMask db 00fh,00eh,00ch,008h
RightClipPlaneMask db 00fh,001h,003h,007h
.code
;---------------------------------------------------------------------------
; Mode X (320x240, 256 colors) rectangle solid colour fill routine.
;
; Based on code originally published in DDJ Mag by M. Abrash
;
; with TASM 2. C near-callable as:
;
; void x_rect_fill_clipped(int StartX, int StartY, int EndX, int EndY,
; unsigned int PageBase, unsigne int color);
;
;
_x_rect_fill_clipped proc
ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
push si ;preserve caller's register variables
push di
mov dx,[_TopClip] ; Compare u.l. Y coord with Top
mov cx,[_BottomClip]
mov ax,[StartY]
mov bx,[EndY]
cmp dx,ax
jle @@CheckBottomClip
cmp dx,bx
jg @@NotVisible
mov [StartY],dx
@@CheckBottomClip:
cmp cx,bx
jg @@CheckLeftClip
cmp cx,ax
jl @@NotVisible
mov [EndY],cx
@@CheckLeftClip:
mov dx,[_LeftClip] ; Compare u.l. Y coord with Top
mov cx,[_RightClip]
mov ax,[StartX]
mov bx,[EndX]
sal dx,2
sal cx,2
cmp dx,ax
jle @@CheckRightClip
cmp dx,bx
jg @@NotVisible
mov [StartX],dx
@@CheckRightClip:
cmp cx,bx
jg RFClipDone
cmp cx,ax
jl @@NotVisible
mov [EndX],cx
jmp RFClipDone
@@NotVisible:
mov ax,1
pop di ; restore registers
pop si
pop bp
ret
_x_rect_fill_clipped endp
;---------------------------------------------------------------------------
; Mode X (320x240, 256 colors) rectangle solid colour fill routine.
;
; Based on code originally published in DDJ Mag by M. Abrash
;
; with TASM 2. C near-callable as:
;
; void x_rect_fill(int StartX, int StartY, int EndX, int EndY,
; unsigned int PageBase, unsigne int color);
;
;
_x_rect_fill proc
ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
push si ;preserve caller's register variables
push di
RFClipDone:
cld
mov ax,[_ScrnLogicalByteWidth]
mul [StartY] ;offset in page of top rectangle scan line
mov di,[StartX]
sar di,2 ;X/4 = offset of first rectangle pixel in scan
add di,ax ;offset of first rectangle pixel in page
add di,[PageBase] ;offset of first rectangle pixel in
; display memory
mov ax,SCREEN_SEG ;point ES:DI to the first rectangle
mov es,ax ; pixel's address
mov dx,SC_INDEX ;set the Sequence Controller Index to
mov al,MAP_MASK ; point to the Map Mask register
out dx,al
inc dx ;point DX to the SC Data register
mov si,[StartX]
and si,0003h ;look up left edge plane mask
mov bh,LeftClipPlaneMask[si] ; to clip & put in BH
mov si,[EndX]
and si,0003h ;look up right edge plane
mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL
mov cx,[EndX] ;calculate # of addresses across rect
mov si,[StartX]
cmp cx,si
jle @@FillDone ;skip if 0 or negative width
dec cx
and si,not 011b
sub cx,si
sar cx,2 ;# of addresses across rectangle to fill - 1
jnz @@MasksSet ;there's more than one byte to draw
and bh,bl ;there's only one byte, so combine the left
; and right edge clip masks
@@MasksSet:
mov si,[EndY]
sub si,[StartY] ;BX = height of rectangle
jle @@FillDone ;skip if 0 or negative height
mov ah,byte ptr [Color] ;color with which to fill
mov bp,[_ScrnLogicalByteWidth] ;stack frame isn't needed any more
sub bp,cx ;distance from end of one scan line to start
dec bp ; of next
@@FillRowsLoop:
push cx ;remember width in addresses - 1
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the left edge
dec cx ;count off left edge byte
js @@FillLoopBottom ;that's the only byte
jz @@DoRightEdge ;there are only two bytes
mov al,00fh ;middle addresses drawn 4 pixels at a pop
out dx,al ;set the middle pixel mask to no clip
mov al,ah ;put color in AL
rep stosb ;draw middle addresses four pixels apiece
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the right edge
@@FillLoopBottom:
add di,bp ;point to start of the next scan line of
; the rectangle
pop cx ;retrieve width in addresses - 1
dec si ;count down scan lines
jnz @@FillRowsLoop
@@FillDone:
pop di ;restore caller's register variables
pop si
pop bp ;restore caller's stack frame
ret
_x_rect_fill endp
;---------------------------------------------------------------------------
; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.
; Upper left corner of pattern is always aligned to a multiple-of-4
; row and column. Works on all VGAs. Uses approach of copying the
; pattern to off-screen display memory, then loading the latches with
; the pattern for each scan line and filling each scan line four
; pixels at a time. Fills up to but not including the column at EndX
; and the row at EndY. No clipping is performed. All ASM code tested
;
;
; Based on code originally published in DDJ Mag by M. Abrash
;
;
; C near-callable as:
;
; void x_rect_pattern_clipped(int StartX, int StartY, int EndX, int EndY,
; unsigned int PageBase, char far * Pattern);
;
;
_x_rect_pattern_clipped proc
ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword
LOCAL NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
sub sp,LocalStk ;allocate space for local vars
push si ;preserve caller's register variables
push di
push ds
mov dx,[_TopClip] ; Compare u.l. Y coord with Top
mov cx,[_BottomClip]
mov ax,[StartY]
mov bx,[EndY]
cmp dx,ax
jle @@CheckBottomClip
cmp dx,bx
jg @@NotVisible
mov [StartY],dx
@@CheckBottomClip:
cmp cx,bx
jg @@CheckLeftClip
cmp cx,ax
jl @@NotVisible
mov [EndY],cx
@@CheckLeftClip:
mov dx,[_LeftClip] ; Compare u.l. Y coord with Top
mov cx,[_RightClip]
mov ax,[StartX]
mov bx,[EndX]
sal dx,2
sal cx,2
cmp dx,ax
jle @@CheckRightClip
cmp dx,bx
jg @@NotVisible
mov [StartX],dx
@@CheckRightClip:
cmp cx,bx
jg RPClipDone
cmp cx,ax
jl @@NotVisible
mov [EndX],cx
jmp RPClipDone
@@NotVisible:
mov ax,1
pop ds
pop di ; restore registers
pop si
mov sp,bp
pop bp
ret
_x_rect_pattern_clipped endp
;---------------------------------------------------------------------------
; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.
; Upper left corner of pattern is always aligned to a multiple-of-4
; row and column. Works on all VGAs. Uses approach of copying the
; pattern to off-screen display memory, then loading the latches with
; the pattern for each scan line and filling each scan line four
; pixels at a time. Fills up to but not including the column at EndX
; and the row at EndY. No clipping is performed. All ASM code tested
;
;
; Based on code originally published in DDJ Mag by M. Abrash
;
;
; C near-callable as:
;
; void x_rect_pattern(int StartX, int StartY, int EndX, int EndY,
; unsigned int PageBase, char far * Pattern);
_x_rect_pattern proc
ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword
LOCAL NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
sub sp,LocalStk ;allocate space for local vars
push si ;preserve caller's register variables
push di
push ds
RPClipDone:
cld
mov ax,SCREEN_SEG ;point ES to display memory
mov es,ax
;copy pattern to display memory buffer
lds si,dword ptr [Pattern] ;point to pattern to fill with
mov di,PATTERN_BUFFER ;point ES:DI to pattern buffer
mov dx,SC_INDEX ;point Sequence Controller Index to
mov al,MAP_MASK ; Map Mask
out dx,al
inc dx ;point to SC Data register
mov cx,4 ;4 pixel quadruplets in pattern
@@DownloadPatternLoop:
mov al,1 ;
out dx,al ;select plane 0 for writes
movsb ;copy over next plane 0 pattern pixel
dec di ;stay at same address for next plane
mov al,2 ;
out dx,al ;select plane 1 for writes
movsb ;copy over next plane 1 pattern pixel
dec di ;stay at same address for next plane
mov al,4 ;
out dx,al ;select plane 2 for writes
movsb ;copy over next plane 2 pattern pixel
dec di ;stay at same address for next plane
mov al,8 ;
out dx,al ;select plane 3 for writes
movsb ;copy over next plane 3 pattern pixel
; and advance address
loop @@DownloadPatternLoop
pop ds
mov dx,GC_INDEX ;set the bit mask to select all bits
mov ax,00000h+BIT_MASK ; from the latches and none from
out dx,ax ; the CPU, so that we can write the
; latch contents directly to memory
mov ax,[StartY] ;top rectangle scan line
mov si,ax
and si,011b ;top rect scan line modulo 4
add si,PATTERN_BUFFER ;point to pattern scan line that
; maps to top line of rect to draw
mov dx,[_ScrnLogicalByteWidth]
mul dx ;offset in page of top rect scan line
mov di,[StartX]
mov bx,di
sar di,2 ;X/4 = offset of first rectangle pixel in scan
add di,ax ;offset of first rectangle pixel in page
add di,[PageBase] ;offset of first rectangle pixel in
; display memory
and bx,0003h ;look up left edge plane mask
mov ah,LeftClipPlaneMask[bx] ; to clip
mov bx,[EndX]
and bx,0003h ;look up right edge plane
mov al,RightClipPlaneMask[bx] ; mask to clip
mov bx,ax ;put the masks in BX
mov cx,[EndX] ;calculate # of addresses across rect
mov ax,[StartX]
cmp cx,ax
jle @@FillDone ;skip if 0 or negative width
dec cx
and ax,not 011b
sub cx,ax
sar cx,2 ;# of addresses across rectangle to fill - 1
jnz @@MasksSet ;there's more than one pixel to draw
and bh,bl ;there's only one pixel, so combine the left
; and right edge clip masks
@@MasksSet:
mov ax,[EndY]
sub ax,[StartY] ;AX = height of rectangle
jle @@FillDone ;skip if 0 or negative height
mov [Height],ax
mov ax,[_ScrnLogicalByteWidth]
sub ax,cx ;distance from end of one scan line to start
dec ax ; of next
mov [NextScanOffset],ax
mov [RectAddrWidth],cx ;remember width in addresses - 1
mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg
; (SC Index still points to Map Mask)
@@FillRowsLoop:
mov cx,[RectAddrWidth] ;width across - 1
mov al,es:[si] ;read display memory to latch this scan
; line's pattern
inc si ;point to the next pattern scan line, wrapping
jnz short @@NoWrap ; back to the start of the pattern if
sub si,4 ; we've run off the end
@@NoWrap:
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
stosb ;draw the left edge (pixels come from latches;
; value written by CPU doesn't matter)
dec cx ;count off left edge address
js @@FillLoopBottom ;that's the only address
jz @@DoRightEdge ;there are only two addresses
mov al,00fh ;middle addresses drawn 4 pixels at a pop
out dx,al ;set middle pixel mask to no clip
rep stosb ;draw middle addresses four pixels apiece
; (from latches; value written doesn't matter)
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
stosb ;draw the right edge (from latches; value
; written doesn't matter)
@@FillLoopBottom:
add di,[NextScanOffset] ;point to the start of the next scan
; line of the rectangle
dec word ptr [Height] ;count down scan lines
jnz @@FillRowsLoop
@@FillDone:
mov dx,GC_INDEX+1 ;restore the bit mask to its default,
mov al,0ffh ; which selects all bits from the CPU
out dx,al ; and none from the latches (the GC
; Index still points to Bit Mask)
pop di ;restore caller's register variables
pop si
mov sp,bp ;discard storage for local variables
pop bp ;restore caller's stack frame
ret
_x_rect_pattern endp
;-----------------------------------------------------------------------
; Mode X (320x240, 256 colors) display memory to display memory copy
; routine. Left edge of source rectangle modulo 4 must equal left edge
; of destination rectangle modulo 4. Works on all VGAs. Uses approach
; of reading 4 pixels at a time from the source into the latches, then
; writing the latches to the destination. Copies up to but not
; including the column at SrcEndX and the row at SrcEndY. No
; clipping is performed. Results are not guaranteed if the source and
; destination overlap.
;
;
; Based on code originally published in DDJ Mag by M. Abrash
;
;C near-callable as:
; void x_cp_vid_rect(int SrcStartX, int SrcStartY,
; int SrcEndX, int SrcEndY, int DestStartX,
; int DestStartY, unsigned int SrcPageBase,
; unsigned int DestPageBase, int SrcBitmapWidth,
; int DestBitmapWidth);
_x_cp_vid_rect proc
ARG SrcStartX:word,SrcStartY:word,SrcEndX:word,SrcEndY:word,DestStartX:word,DestStartY:word,SrcPageBase:word,DestPageBase:word,SrcBitmapW:word,DestBitmapW:word
LOCAL SrcNextOffs:word,DestNextOffs:word,RectAddrW:word,Height:word=LocalStk
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
sub sp,LocalStk ;allocate space for local vars
push si ;preserve caller's register variables
push di
push ds
cld
mov dx,GC_INDEX ;set the bit mask to select all bits
mov ax,00000h+BIT_MASK ; from the latches and none from
out dx,ax ; the CPU, so that we can write the
; latch contents directly to memory
mov ax,SCREEN_SEG ;point ES to display memory
mov es,ax
mov ax,[DestBitmapW]
shr ax,2 ;convert to width in addresses
mul [DestStartY] ;top dest rect scan line
mov di,[DestStartX]
sar di,2 ;X/4 = offset of first dest rect pixel in
; scan line
add di,ax ;offset of first dest rect pixel in page
add di,[DestPageBase] ;offset of first dest rect pixel
; in display memory
mov ax,[SrcBitmapW]
sar ax,2 ;convert to width in addresses
mul [SrcStartY] ;top source rect scan line
mov si,[SrcStartX]
mov bx,si
sar si,2 ;X/4 = offset of first source rect pixel in
; scan line
add si,ax ;offset of first source rect pixel in page
add si,[SrcPageBase] ;offset of first source rect
; pixel in display memory
and bx,0003h ;look up left edge plane mask
mov ah,LeftClipPlaneMask[bx] ; to clip
mov bx,[SrcEndX]
and bx,0003h ;look up right edge plane
mov al,RightClipPlaneMask[bx] ; mask to clip
mov bx,ax ;put the masks in BX
mov cx,[SrcEndX] ;calculate # of addresses across
mov ax,[SrcStartX] ; rect
cmp cx,ax
jle @@CopyDone ;skip if 0 or negative width
dec cx
and ax,not 011b
sub cx,ax
sar cx,2 ;# of addresses across rectangle to copy - 1
jnz @@MasksSet ;there's more than one address to draw
and bh,bl ;there's only one address, so combine the left
; and right edge clip masks
@@MasksSet:
mov ax,[SrcEndY]
sub ax,[SrcStartY] ;AX = height of rectangle
jle @@CopyDone ;skip if 0 or negative height
mov [Height],ax
mov ax,[DestBitmapW]
sar ax,2 ;convert to width in addresses
sub ax,cx ;distance from end of one dest scan line
dec ax ; to start of next
mov [DestNextOffs],ax
mov ax,[SrcBitmapW]
sar ax,2 ;convert to width in addresses
sub ax,cx ;distance from end of one source scan line
dec ax ; to start of next
mov [SrcNextOffs],ax
mov [RectAddrW],cx ;remember width in addresses - 1
mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg
; (SC Index still points to Map Mask)
mov ax,es ;DS=ES=screen segment for MOVS
mov ds,ax
@@CopyRowsLoop:
mov cx,[RectAddrW] ;width across - 1
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
movsb ;copy the left edge (pixels go through
; latches)
dec cx ;count off left edge address
js @@CopyLoopBottom ;that's the only address
jz @@DoRightEdge ;there are only two addresses
mov al,00fh ;middle addresses are drawn 4 pix per go
out dx,al ;set the middle pixel mask to no clip
rep movsb ;draw the middle addresses four pix per go
; (pixels copied through latches)
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
movsb ;draw the right edge (pixels copied through
; latches)
@@CopyLoopBottom:
add si,[SrcNextOffs] ;point to the start of
add di,[DestNextOffs] ; next source & dest lines
dec word ptr [Height] ;count down scan lines
jnz @@CopyRowsLoop
@@CopyDone:
mov dx,GC_INDEX+1 ;restore the bit mask to its default,
mov al,0ffh ; which selects all bits from the CPU
out dx,al ; and none from the latches (the GC
; Index still points to Bit Mask)
pop ds
pop di ;restore caller's register variables
pop si
mov sp,bp ;discard storage for local variables
pop bp ;restore caller's stack frame
ret
_x_cp_vid_rect endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copy a rectangular region of a VGA screen, with x coordinates
; rounded to the nearest byte -- source and destination may overlap.
;
; C near-callable as:
;
; void x_shift_rect (WORD SrcLeft, WORD SrcTop,
; WORD SrcRight, WORD SrcBottom,
; WORD DestLeft, WORD DestTop, WORD ScreenOffs);
;
; SrcRight is rounded up, and the left edges are rounded down, to ensure
; that the pixels pointed to by the arguments are inside the rectangle.
;
; The width of the rectangle in bytes (width in pixels / 4)
; cannot exceed 255.
;
; ax, bx, cx, dx, and es eat hot lead.
;
; This function was written by Matthew MacKenzie
; matm@eng.umd.edu
align 2
_x_shift_rect proc
ARG SrcLeft,SrcTop,SrcRight,SrcBottom,DestLeft,DestTop,ScreenOffs:word
LOCAL width_temp:word=LocalStk
push bp
mov bp, sp
sub sp, LocalStk
push si
push di
push ds
; find values for width & x motion
mov si, SrcLeft ; source x in bytes
sar si, 2
mov di, DestLeft ; destination x in bytes
sar di, 2
mov bx, SrcRight ; right edge of source in bytes, rounded up
add bx, 3
sar bx, 2
sub bx, si
mov ax, bx ; width - 1
inc bx ; we'll use this as an offset for moving up or down
mov width_temp, bx
cld ; by default, strings increment
cmp si, di
jge @@MovingLeft
; we're moving our rectangle right, so we copy it from right to left
add si, ax ; source & destination will start on the right edge
add di, ax
neg bx
std ; strings decrement
@@MovingLeft:
; find values for height & y motion
mov cx, _ScrnLogicalByteWidth ; bytes to move to advance one line
mov ax, SrcTop
mov dx, DestTop ; default destination y
cmp ax, dx
jge @@MovingUp
; we're moving our rectangle down, so we copy it from bottom to top
mov ax, SrcBottom ; source starts at bottom
add dx, ax ; add (height - 1) to destination y
sub dx, SrcTop
neg cx ; advance up screen rather than down
@@MovingUp:
push dx ; save destination y during multiply
mul _ScrnLogicalByteWidth
add si, ax ; add y in bytes to source
pop ax ; restore destination y
mul _ScrnLogicalByteWidth
add di, ax ; add y in bytes to destination
sub cx, bx ; final value for moving up or down
add si, ScreenOffs ; source & destination are on the same screen
add di, ScreenOffs
mov dx, SC_INDEX ; set map mask to all four planes
mov ax, 00f02h
out dx, ax
mov dx, GC_INDEX ; set bit mask to take data from latches
mov ax, BIT_MASK ; rather than CPU
out dx, ax
mov ax, SCREEN_SEG ; source and destination are VGA memory
mov es, ax
mov ds, ax
mov ah, byte ptr width_temp ; width in bytes should fit in 8 bits
mov bx, SrcBottom ; height - 1
sub bx, SrcTop
mov dx, cx ; bytes to add to advance one line
xor ch, ch ; ready to rock
@@LineLoop:
mov cl, ah ; load width in bytes
rep movsb ; move 4 pixels at a time using latches (YOW!)
add si, dx ; advance source by one line
add di, dx ; advance destination by one line
dec bx ; line counter
jge @@LineLoop ; 0 still means one more to go
mov dx, GC_INDEX + 1; set bit mask to take data from CPU (normal setting)
mov al, 0ffh
out dx, al
; kick
pop ds
pop di
pop si
mov sp, bp
pop bp
ret
_x_shift_rect endp
end